import logging
from os import abort

from sqlalchemy import func

from blls.base_bll import BaseBLL
from dtos.result import Result
from enumobjects.general_enum import YesOrNoEnum
from models.annotation_models.annotation_model import Annotation
from models.label_models.label import Label
from models.project_models.project_model import Project
from utils.common_util import CommonUtil
from utils.guid_util import GUIDUtil


class LabelBLL(BaseBLL):
    def get_label_by_project(self, data):
        #查询是否存在project
        project = self.db_session.query(Project).filter(Project.project_id == data['project_id'],
                                                        Project.is_delete == YesOrNoEnum.NO.value).first()
        if project is None:
            return Result.error_result(message="Project not found")
        #根据projectid查询所有label数据
        label_info = self.db_session.query(Label).filter(Label.project_id == project.project_id,
                                                         Label.is_delete == YesOrNoEnum.NO.value).all()
        if label_info is None:
            return Result.error_result(message="label not found")
        data_list = []
        for i in label_info:
            info = {
                "color": i.color,
                "created": CommonUtil.convert_timestamp_to_dt(i.create_time),
                "id": i.id,
                "label_id": i.label_id,
                "modified": CommonUtil.convert_timestamp_to_dt(i.last_update_time),
                "name": i.name,
                "project_id": data["project_id"],
                "task_category_id": project.task_category_id,
            }
            data_list.append(info)
        return Result.success_result(data=data_list)

    def add_label(self, data):
        project = self.db_session.query(Project).filter(Project.project_id == data['project_id'],
                                                        Project.is_delete == YesOrNoEnum.NO.value).first()
        if project is None:
            return Result.error_result(message="Project does not exist")
        new_label = Label(**{
            "project_id": project.project_id,
            "name": data['name'],
            "color": data['color'],
        })
        if new_label.id is None:
            ann = self.db_session.query(func.max(Label.id)).filter_by(project_id=new_label.project_id,
                                                                      is_delete=YesOrNoEnum.NO.value).one()[0]
            if ann is None:
                ann = 0
            new_label.id = ann + 1
        if new_label.color == "":
            colors = self.db_session.query(Label).with_entities(Label.color).filter(
                Label.project_id == new_label.project_id,
                Label.is_delete == YesOrNoEnum.NO.value
            ).all()
            colors = [c[0] for c in colors]
            new_label.color = CommonUtil.rand_hex_color(colors)

        # 3. cols must be unique within project
        cols = ["id", "name", "color"]
        labels = self.db_session.query(Label).filter(Label.project_id == new_label.project_id,
                                                     Label.is_delete == YesOrNoEnum.NO.value).all()
        rets, unique = CommonUtil.unique_within_project(labels, [new_label], cols)
        if not unique[0]:
            not_unique_cols = ", ".join([c for c, u in zip(cols, rets) if not u])
            return Result.error_result(message=f"Label {not_unique_cols} is not unique")
        label = Label(**{
            "guid": GUIDUtil.generate(),
            "id": new_label.id,
            "project_id": new_label.project_id,
            "name": new_label.name,
            "color": new_label.color,
            "create_time": CommonUtil.get_timestamp()
        })
        try:
            self.db_session.begin(subtransactions=True)
            self.db_session.add(label)
            self.db_session.commit()
            return Result.success_result(message="添加成功")
        except Exception as ex:
            message = "添加错误，原因是:%s" % str(ex)
            logging.info(message)
            self.db_session.rollback()
            return Result.error_result(message=message)
